from django.shortcuts import render, redirect, HttpResponse
from io import BytesIO
from django import forms
from app03 import models
from app03.utils.bootrstap import BootrsapForm, BootrsapModelForm
from app03.utils.code import check_code
from app03.utils.encrypt import md5
from django.core.exceptions import ValidationError


class LoginForm( BootrsapForm ):
    user = forms.CharField(
        label='用户名',
        required=True,
        min_length=3,
        max_length=10,
        widget=forms.TextInput( attrs={'class': 'form-control'} ),
        error_messages={
            'required': '用户名不能为空',
            'min_length': '长度不能小于3个字符',
            'max_length': '长度不能大于10个字符'
        }
    )
    pwd = forms.CharField(
        label='密码',
        required=True,
        min_length=3,
        max_length=32,
        widget=forms.PasswordInput( attrs={'class': 'form-control'} ),
        error_messages={
            'required': '用户名不能为空',
            'min_length': '长度不能小于3个字符',
            'max_length': '长度不能大于32个字符'
        }
    )
    # 创建一个字段
    com_password = forms.CharField(
        label='确认密码',
        # 保留原密码的值render_value=True
        widget=forms.PasswordInput( render_value=True )
    )
    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput,
        required=True
    )

    # 给密码进行md5加密
    def clean_password(self):
        pwd = self.cleaned_data.get( 'pwd' )
        return md5( pwd )
        # 钩子函数clean+字段名

    def clean_com_password(self):
        # 获取到验证通过用户输入的确认密码  通过md5()给确认密码加密
        comstf = self.cleaned_data.get( 'com_password' )
        print( comstf )
        # 获取到验证通过用户输入密码
        pwd = self.cleaned_data.get( 'pwd' )
        # print(pwd)
        if comstf != pwd:
            raise ValidationError( '密码输入不一致' )
        # # # 将com_password的值 返回给cleaned_data  在通过form.save()保存到数据库中
        # return comstf


def form_login(request):
    if request.method == 'GET':
        form = LoginForm()
        return render( request, 'login.html', {'form': form} )
    else:
        form = LoginForm( data=request.POST )
        if form.is_valid():
            # print(pwd)
            # print(form.cleaned_data)
            # form.cleaned_data={'username': 'tbfaj864', 'password': 'cb68dabb852f388164f69156295dd297',code:xxxx}

            # 验证码的校验
            # 把验证码从数组删除并返回code
            user_input_code = form.cleaned_data.pop( 'code' )
            # 获取到用户输入的验证码
            codes = request.session.get( 'image_code' )
            # 当用户输入的验证码不等于生成的验证码返回错误提示
            if user_input_code.upper() != codes.upper():
                form.add_error( 'code', '验证码错误' )
                return render( request, 'login.html', {"form": form} )
            user = form.cleaned_data['user']
            pwd = form.cleaned_data['pwd']
            models.login.objects.create( name=user, pwd=pwd )
            # # 获取到的数据去到数据库中校验
            # admin_object = models.login.objects.filter( **form.cleaned_data ).first()
            # # 当获取的数据为none时
            # if not admin_object:
            #     form.add_error( 'password', '用户名或密码错误' )
            #     return render( request, 'login.html', {"form": form} )
            # # 用户名跟密码正确
            # request.session['info'] = {"id": admin_object.id, "name": admin_object.user_n}
            # # session可以保存7天
            # request.session.set_expiry( 60 * 60 * 24 * 7 )
            return redirect( '/form/sign/' )
    return render( request, 'login.html', {"form": form} )


# 生成随机验证码
def image_code(request):
    """生成验证码图片"""

    # 调用pillow函数，生成图片
    img, code_string = check_code()
    print( code_string )
    # 写入到session中(以便后面获取验证码进行校验)
    request.session['image_code'] = code_string
    # 给session设置超时60s
    request.session.set_expiry( 60 )

    stream = BytesIO()
    img.save( stream, 'png' )
    return HttpResponse( stream.getvalue() )


# 登录界面
class SignForm( BootrsapForm ):
    name = forms.CharField(
        label='用户名',
        required=True,
        min_length=3,
        max_length=10,
        widget=forms.TextInput( attrs={'class': 'form-control'} ),
        error_messages={
            'required': '用户名不能为空',
            'min_length': '长度不能小于3个字符',
            'max_length': '长度不能大于10个字符'
        } )
    pwd = forms.CharField(
        label='密码',
        required=True,
        min_length=3,
        max_length=32,
        widget=forms.PasswordInput( attrs={'class': 'form-control'} ),
        error_messages={
            'required': '用户名不能为空',
            'min_length': '长度不能小于3个字符',
            'max_length': '长度不能大于32个字符'
        }
    )


    code = forms.CharField(
        label="验证码",
        widget=forms.TextInput,
        required=True
    )
    # 给密码进行md5加密
    def clean_password(self):
        pwd = self.cleaned_data.get( 'pwd' )
        return md5( pwd )


def form_sign(request):
    if request.method == 'GET':
        form = SignForm()
        return render( request, 'sign.html', {'form': form} )
    else:
        form = SignForm( data=request.POST )
        if form.is_valid():
            # print()
            print( form.cleaned_data )
            user_input_code = form.cleaned_data.pop( 'code' )
            # 获取到用户输入的验证码
            codes = request.session.get( 'image_code' )
            # 当用户输入的验证码不等于生成的验证码返回错误提示
            if user_input_code.upper() != codes.upper():
                form.add_error( 'code', '验证码错误' )
                return render( request, 'sign.html', {"form": form} )
            # 获取到的数据去到数据库中校验
            admin_object = models.login.objects.filter( **form.cleaned_data ).first()
            # 当获取的数据为none时
            if not admin_object:
                form.add_error( 'pwd', '用户名或密码错误' )
                return render( request, 'sign.html', {"form": form} )
            # 用户名跟密码正确
            request.session['info'] = {"id": admin_object.id, "name": admin_object.name}
            # # session可以保存7天
            request.session.set_expiry( 60 * 60 * 24 * 7 )
            return redirect( '/user/list/' )
    return render( request, 'sign.html', {"form": form} )

#注销
def form_out(request):
    request.session.clear()
    return redirect('/form/sign/')